﻿/*****************************************介绍*****************************************
 * 作者：Ywh
 * 创建时间：2023-02-24　04:55:31
 * 功能：日志管理器 (该管理器的目的是再构建是方便剔除日志代码)
 * 使用规则：
 *          1、Log(XXX) API主要用于调试内容，我们大部分情况下使用这个API
 *          2、LogWarning(XXX) API用于生成警告信息，该打印信息将永远存在
 *          3、LogError(XXX) API用于生成错误信息，该打印信息将永远存在
 * 正确使用方式：
 *          1、在调试的地方使用Log(XXX)
 *          2、在需要警告的地方使用LogWarning(XXX)
 *          3、在出错的地方使用LogError(XXX)
 * 遵循以上规则就可以在项目中随意打印日志了，在最终发布时可以轻松剔除掉调试代码（Log(XXX)）
**************************************************************************************/

using System.Text;
using UnityEngine;
using system = System.Diagnostics;

namespace Game.Framework
{
    public static class LogManager
    {
        public const string DEFINE = "DEBUG";

        [system.Conditional(DEFINE)]
        public static void Log(object message, params string[] tags) => PrintLog(LogType.Info, message, tags: tags);

        [system.Conditional(DEFINE)]
        public static void Log(object message, Object context, params string[] tags) => PrintLog(LogType.Info, message, context, tags: tags);

        [system.Conditional(DEFINE)]
        public static void LogWarning(object message, params string[] tags) => PrintLog(LogType.Warning, message, tags: tags);

        [system.Conditional(DEFINE)]
        public static void LogWarning(object message, Object context, params string[] tags) => PrintLog(LogType.Warning, message, context, tags: tags);

        public static void LogError(object message, params string[] tags) => PrintLog(LogType.Error, message, tags: tags);

        public static void LogError(object message, Object context, params string[] tags) => PrintLog(LogType.Error, message, context, tags: tags);

        private static void AppendLog(LogType type, StringBuilder sb, string content, string color)
        {
#if DEBUG
            sb.Append($"[{System.DateTime.Now:yyyy-MM-dd HH.mm.ss.fff}] ");
#elif !UNITY_EDITOR && DEBUG
            sb.Append($"[{System.DateTime.Now:yyyy-MM-dd HH.mm.ss.fff}] ");
            switch (type)
            {
                case LogType.Info:
                    sb.Append($"[{content}] ");
                    break;
                case LogType.Warning:
                case LogType.Error:
                    sb.Append($"<color={color}>[{content}]</color> ");
                    break;
            }
#elif !DEBUG
            sb.Append($"[{content}] ");
#endif
        }

        private static string GetLogContent(LogType type, object message, params string[] tags)
        {
            if (message == null) return "";
            string tagColor = "#D2D2D2";
            StringBuilder result = new StringBuilder(string.Empty);
            switch (type)
            {
                case LogType.Info:
                    AppendLog(type, result, "Info   ", tagColor);
                    break;
                case LogType.Warning:
                    tagColor = "orange";
                    AppendLog(type, result, "Warning", tagColor);
                    break;
                case LogType.Error:
                    tagColor = "red";
                    AppendLog(type, result, "Error  ", tagColor);
                    break;
            }

            string tagStr = tags.Length > 0 ? $"[{string.Join("] [", tags)}]" : string.Empty;
#if !DEBUG
            result.Append(tagStr);
#else
            switch (type)
            {
                case LogType.Info:
                    result.Append(tagStr);
                    break;
                case LogType.Warning:
                case LogType.Error:
                    result.Append($"<color={tagColor}>{tagStr}</color>");
                    break;
            }
#endif
            if (result.Length > 0)
                result.Append("\u3000");

            if (message is string && string.IsNullOrEmpty(message.ToString()))
                return "";

            result.Append(message.ToString());

            return result.ToString();
        }

        private static void PrintLog(LogType type, object message, Object context = null, params string[] tags)
        {
            string log = GetLogContent(type, message, tags);
            if (string.IsNullOrEmpty(log)) return;

            switch (type)
            {
                case LogType.Info:
                    Debug.Log(log, context);
                    break;
                case LogType.Warning:
                    Debug.Log(log, context);
                    break;
                case LogType.Error:
                    Debug.LogError(log, context);
                    break;
            }
        }

        private enum LogType
        {
            Info,
            Warning,
            Error,
        }
    }
}